package core

import (
	"context"
	"fmt"
	"net/http"
	"os"
	"os/signal"
	"sync"
	"syscall"
	"time"

	"github.com/golang/glog"
)

// HandlerFunc 定义http处理函数
type HandlerFunc func(http.ResponseWriter, *http.Request)

// ShutdownFunc 函数类型
type ShutdownFunc func(string) error

// server 实现ServeHTTP接口的引擎
type server struct {
	responseLog      bool
	srv              *http.Server
	router           map[string]HandlerFunc
	middlewares      []HandlerFunc
	handlers         []HandlerFunc
	shutdownCallback ShutdownFunc
	shutdownFinished chan struct{}
}

// addRoute 添加路由
func (s *server) addRoute(method string, pattern string, handler HandlerFunc) {
	key := method + "-" + pattern
	s.router[key] = handler
}

// Post 方式请求
func (s *server) Post(pattern string, handler HandlerFunc) {
	s.addRoute("POST", pattern, handler)
}

// Get 方式请求
func (s *server) Get(pattern string, handler HandlerFunc) {
	s.addRoute("GET", pattern, handler)
}

// ServeHTTP 实现服务处理
func (s *server) ServeHTTP(rsp http.ResponseWriter, req *http.Request) {
	key := req.Method + "-" + req.URL.Path
	if handler, ok := s.router[key]; ok {
		start := time.Now()
		s.Next(rsp, req)
		handler(rsp, req)
		if s.responseLog {
			glog.Info("响应：", time.Now().Sub(start), "秒")
		}
	} else {
		fmt.Fprintf(rsp, "404 NOT FOUND: %s\n", req.URL)
		return
	}
}

// Next 带中间件处理请求
func (s *server) Next(rsp http.ResponseWriter, req *http.Request) {
	slen := len(s.middlewares)
	for i := 0; i < slen; i++ {
		s.middlewares[i](rsp, req)
	}
}

// 创建server实例
func New() *server {
	return &server{
		router: make(map[string]HandlerFunc),
	}
}

// Run 服务监听启动
func (s *server) Run(addr string) (err error) {
	// 创建http server
	s.srv = &http.Server{
		Addr:    addr,
		Handler: s,
	}
	var wg sync.WaitGroup
	wg.Add(1)
	// 监听启动服务
	go func(wg *sync.WaitGroup) {
		defer func() {
			if err := recover(); err != nil {
				glog.Info("监听出错！ ", err)
			}
			wg.Done()
		}()
		if err := s.srv.ListenAndServe(); err != nil {
			glog.Error("Listen: %s\n", err)
		}
	}(&wg)
	// 注册关闭函数
	s.shutdownCallback = ShutdownFunc(func(str string) error {
		// 处理关闭业务
		time.Sleep(time.Millisecond * 500)
		s.shutdownFinished <- struct{}{}
		return nil
	})

	wg.Add(1)
	// 优雅关闭
	go func(wg *sync.WaitGroup) {
		defer func() {
			if err := recover(); err != nil {
				glog.Info("优雅关闭出错！ ", err)
			}
			wg.Done()
		}()
		s.GracefulShutdown()
	}(&wg)

	wg.Wait()
	return
}

// GracefulShutdown 优雅关闭
func (s *server) GracefulShutdown() {
	quit := make(chan os.Signal)
	signal.Notify(quit, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGUSR1, syscall.SIGUSR2)
	<-quit
	glog.Info("开始关闭服务 ...")
	t := time.Now()
	s.shutdownFinished = make(chan struct{})
	// 1s超时
	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
	go s.shutdownCallback("")
	select {
	case <-ctx.Done():
	case <-s.shutdownFinished:
	}
	defer func() {
		cancel()
		close(s.shutdownFinished)
		close(quit)
		glog.Info("关闭耗时：", time.Now().Sub(t))
	}()
	if err := s.srv.Shutdown(ctx); err != nil {
		glog.Fatal("服务关闭失败:", err)
	}
	glog.Info("服务停止退出！")
}

// Use 注册中间件
func (s *server) Use(middlewares ...HandlerFunc) {
	s.middlewares = append(s.middlewares, middlewares...)
}
